﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Reflection;



namespace SwAddinHelpersComExtender
{
    public static class ReflectionExtension
    {
        public static EventInfo[] GetPartDocEvents()
        {
            SolidWorks.Interop.sldworks.PartDocClass doc = new SolidWorks.Interop.sldworks.PartDocClass();
            return doc.GetType().GetEvents();
        }

        public static EventInfo GetPartDocEvent(string EventName)
        {
            SolidWorks.Interop.sldworks.PartDocClass doc = new SolidWorks.Interop.sldworks.PartDocClass();
            return doc.GetType().GetEvent(EventName);
        }

        public static object WrapPartDocClass(object comObject)
        {
            return Marshal.CreateWrapperOfType(comObject, typeof(SolidWorks.Interop.sldworks.PartDocClass));
        }
    }

    public static class TypeConverterExtension
    {
        public static Type GetManagedTypeForSWObject(this object comObject, bool ReturnInterface = true)
        {
            Type returnType = null;

            Assembly asm = typeof(SolidWorks.Interop.sldworks.SldWorksClass).Assembly;

            IntPtr ukwn = Marshal.GetIUnknownForObject(comObject);

            foreach (Type t in asm.GetTypes())
            {
                if(t.FullName.StartsWith("SolidWorks"))
                {
                    Guid gid = t.GUID;
                    if (t.IsInterface & gid != Guid.Empty)
                    {
                        IntPtr oPtr = IntPtr.Zero;
                        Marshal.QueryInterface(ukwn, ref gid, out oPtr);

                        if (!oPtr.Equals(IntPtr.Zero))
                        {
                            if (ReturnInterface && t.Name.StartsWith("I"))
                            {
                                Marshal.Release(oPtr);
                                returnType = t;
                                break;
                            }
                            else if (!ReturnInterface && !t.Name.StartsWith("I"))
                            {
                                Marshal.Release(oPtr);
                                returnType = t;
                                break;
                            }
                            
                            Marshal.Release(oPtr);
                        }
                    }
                    
                }
            }

            if (! ukwn.Equals(IntPtr.Zero)) Marshal.Release(ukwn);
            return returnType;
        }

        public static List<Type> GetManagedTypesForSWObject(this object comObject)
        {
            if (comObject == null) 
                return new List<Type>();

            Assembly asm = typeof(SolidWorks.Interop.sldworks.SldWorksClass).Assembly;

            IntPtr ukwn = Marshal.GetIUnknownForObject(comObject);

            List<Type> typeList = new List<Type>();

            foreach (Type t in asm.GetTypes())
            {
                if (t.FullName.StartsWith("SolidWorks"))
                {
                    Guid gid = t.GUID;
                    if (t.IsInterface & gid != Guid.Empty)
                    {
                        IntPtr oPtr = IntPtr.Zero;
                        Marshal.QueryInterface(ukwn, ref gid, out oPtr);

                        if (oPtr != IntPtr.Zero)
                        {
                            typeList.Add(t);
                            Marshal.Release(oPtr);
                        }
                    }
                }
            }

            if (! ukwn.Equals(IntPtr.Zero)) Marshal.Release(ukwn);
            return typeList;

        }
    }
}
